#ifndef __VCPPEFLITEDLL_H
#define __VCPPEFLITEDLL_H

// VCppEFLiteDll.h

#include <sstream>
#include <iostream>
#include <string>
#include <list>
#include <vector>

using namespace std;

#define DllExport   __declspec( dllexport )
#define CD ColumnDefinition
#define P Predicate
#define BP BinPred


namespace EFLite 
{

enum Types {
		INT = 1,
		FLOAT,
		VARCHAR,
		DATE,
		TIME
	};

#pragma region Forward Declarations
	class Predicate;
#pragma endregion
	
#pragma region Data Type Declarations 

#pragma region Class Cell

class Cell { //Abstract
	public:
		virtual bool HasValue() = 0;
		virtual Types GetTypeId() = 0;
		virtual string ToString() = 0;
		virtual int CompareTo(Cell* c) = 0;
};

#pragma endregion //Abstract

#pragma region Class Date
	
class Date : public Cell {
		int year, month, day;
		void init(int year, int month, int day);
		void init(string _Value);
		bool IsValid(int year, int month, int day);
	public:
		//Constructors:
		Date(string _Value) { init(_Value); }
		Date(int _year, int _month, int _day) { init(_year,_month,_day); }
		
		//Accessor Methods:	
		int GetYear();
		int GetMonth();
		int GetDay();
		
		//Virtual Methods:
		virtual bool Cell::HasValue();
		virtual Types Cell::GetTypeId();
		virtual string Cell::ToString();
		virtual int Cell::CompareTo(Cell* c);
};
	
#pragma endregion : Cell

#pragma region Class Time

class Time : public Cell {
		int hours, minutes, seconds;
		void init(int hours, int minutes, int seconds);
		void init(string _Value);
		bool IsValid(int hours, int minutes, int seconds);
	public:
		//Constructors:
		Time(int _hours, int _minutes, int _seconds) { init(_hours,_minutes,_seconds); }
		Time(string _Value) { init(_Value); }
		
		//Accessor Methods:
		int GetHours();
		int GetMinutes();
		int GetSeconds();
		
		//Virtual Overrides
		virtual bool Cell::HasValue();
		virtual Types Cell::GetTypeId();
		virtual string Cell::ToString();
		virtual int Cell::CompareTo(Cell* c);
};

#pragma endregion : Cell

#pragma region Class String

class String : public Cell {
		string Value;
		unsigned int MaxSize;
	public:
		//Constructor
		String(const string _Value, unsigned int _MaxSize = 255){
			Value = _Value;
			if(_MaxSize > 255)
				throw new exception("Exceeded maximum size limit of 255 characters.");
			else
				MaxSize = _MaxSize;
		}
		//Accessor Methods:
		string GetValue();
		int GetMaxSize();

		//Mutator Methods:
		void SetValue(string s);

		//Virtual Methods:
		virtual bool Cell::HasValue();
		virtual Types Cell::GetTypeId();
		virtual string Cell::ToString();
		virtual int Cell::CompareTo(Cell* c);
};

#pragma endregion : Cell

#pragma region Class Int
	
class Int : public Cell {
	public:
		int Value;
		virtual bool Cell::HasValue();
		virtual Types Cell::GetTypeId();
		virtual string Cell::ToString();
		virtual int Cell::CompareTo(Cell* c);
		Int(int _Value) { Value = _Value; }
		Int(string _Value){
			if(_Value == "NULL" || _Value == "null")
				Value = NULL;
			else
				Value = atoi(_Value.c_str());
		}
};

#pragma endregion : Cell
	
#pragma region Class Float

class Float : public Cell {
	public:
		float Value;
		virtual bool Cell::HasValue();
		virtual Types Cell::GetTypeId();
		virtual string Cell::ToString();
		virtual int Cell::CompareTo(Cell* c);
		Float(float _Value) { Value = _Value; }
		Float(string _Value){
			if(_Value == "NULL" || _Value == "null")
				Value = NULL;
			else
				Value = (float)atof(_Value.c_str());
		}
};

#pragma endregion : Cell

#pragma endregion Declarations for types of data to store in DB

#pragma region Data Object Declarations

#pragma region Class ColumnDefinition

class DllExport ColumnDefinition {
		string Name;
		Types Type;
		bool Key;
	public:
		//Constructors:
		ColumnDefinition(string _Name, Types _Type);
		ColumnDefinition(string _Name, Types _Type, bool _Key);
		ColumnDefinition(const ColumnDefinition& CopyCD);
		
		//Accessor Methods:
		string GetName() const;
		Types GetType() const;
		bool GetKey() const;
		string ToString() const;
		
		//Mutator Methods:
		void Rename(string n);
};

#pragma endregion

#pragma region Class Entity
/*	From Rev 35
	//Methods
	int InsertByAddr(void* Record);			//1
	int Insert(void *Record, ...);			//2
	int Remove(Predicate *p);				//2					 //1 ready for testing
	int Update(Predicate *p, CD* cd);		//3					 //2 need minor feedback
	Entity* Where(Predicate *p);			//2					 //3 moderate feedback require or moderate work remaining
	int Count(string columnName);			//1					 //4 much work needed
	int Sum(string columnName);				//2					 //5 no work completed
	void* Min(string columnName);			//1
	void* Max(string columnName);			//1
	int RenameColumn(string o, string n);	//1
	string GetName() const;					//1
	string ToMetaString() const;			//1		
	string ToString() const;				//1*/
class DllExport Entity {
		string Name;
	public:
		//Public Data:
		list<void*> Rows;
		list<CD> Columns;

		//Constructors:
		Entity();
		Entity(string _Name, ColumnDefinition _ColumnDefinitions[]);
		Entity(string _Name, list<CD> ColumnDefinitions);
		Entity(const Entity& CopyEntity);
		
		//Accessor Methods:			
		Entity* Where(Predicate *p);		
		int Count(string columnName);		
		int Sum(string columnName);			
		void* Min(string columnName);		
		void* Max(string columnName);		
		string GetName() const;				
		string ToMetaString() const;		
		string ToString() const;

		//Mutator Methods:
		int RenameColumn(string o, string n);
		int InsertByAddr(void* Record);		
		int Insert(void *Record, ...);		
		int Remove(Predicate *p);			
		int Update(Predicate *p, CD* cd);

		//Operator Overloads:
		Entity& operator+= (Entity _Entity);
		bool Entity::operator ==(Entity& _Entity);
};

#pragma endregion

#pragma region  Class DBContext
/*	From Rev 35
	int Create(Entity &entity);							//2
	int Delete(Entity &entity);							//1					//1 ready for testing					
	int ExecuteScalar(string query, Int *result);		//5					//2 need minor feedback		
	int ExecuteScalar(string query, Float *result);		//5					//3 moderate feedback require or moderate work remaining		
	int ExecuteScalar(string query, Date *result);		//5					//4 much work needed
	int ExecuteScalar(string query, Time *result);		//5					//5 no work completed
	int ExecuteScalar(string query, String *result);	//5
	int ExecuteReader(string query, Entity *result);	//1
	int ExecuteNonQuery(string query);					//1
	Entity& operator[] (string _Name);					//1
	Entity& operator[] (string _Names[]);				//3
	string ToString() const;							//1
	DBContext(string _Name);							//1*/
class DllExport DBContext {
		list<Entity> Entities;
		string Name;
	public:
		//Constructors:
		DBContext(string _Name);

		//Accessor Methods:
		int ExecuteReader(string query, Entity *result);
		int ExecuteNonQuery(string query);	

		//Mutator Methods:
		int Create(Entity &entity);						
		int Delete(Entity &entity);						
		int ExecuteScalar(string query, Int *result);	
		int ExecuteScalar(string query, Float *result);	
		int ExecuteScalar(string query, Date *result);	
		int ExecuteScalar(string query, Time *result);	
		int ExecuteScalar(string query, String *result);
					
		//Operator Overloads:
		Entity& operator[] (string _Name);				
		Entity& operator[] (string _Names[]);			
		string ToString() const;						
};

#pragma endregion

#pragma endregion Data Object Declarations

#pragma region Predicate Classes Declarations
	
#pragma region class Predicate

class Predicate { //abstract
	public:
		virtual bool Evaluate(void* Row, list<CD> *cds) = 0;
};

#pragma endregion //Abstract

#pragma region class BinPred

class BinPred : public P {
		string *ls, *rs;
		Cell *lc, *rc;
	protected: 
		virtual bool Compare(Cell *l, Cell *r) = 0;
	public:
		//Constructors:
		BP(string &l, string &r);
		BP(string &l, Cell *r);
		BP(Cell *l, string r);
		BP(Cell *l, Cell *r);
		//Virtual Methods:
		virtual bool P::Evaluate(void* Row, list<CD> *cds);
};

#pragma endregion :Predicate

#pragma region class EQ
class EQ : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		EQ(string l, string r):BP(l,r){};
		EQ(string l, Cell *r):BP(l,r){};
		EQ(Cell *l, string r):BP(l,r){};
		EQ(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion  :BP

#pragma region class NEQ
class NEQ : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		NEQ(string l, string r):BP(l,r){};
		NEQ(string l, Cell *r):BP(l,r){};
		NEQ(Cell *l, string r):BP(l,r){};
		NEQ(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion :BP

#pragma region class GT
class GT : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		GT(string l, string r):BP(l,r){};
		GT(string l, Cell *r):BP(l,r){};
		GT(Cell *l, string r):BP(l,r){};
		GT(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion  :BP

#pragma region class LT
class LT : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		LT(string l, string r):BP(l,r){};
		LT(string l, Cell *r):BP(l,r){};
		LT(Cell *l, string r):BP(l,r){};
		LT(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion  :BP

#pragma region class GTE
class GTE : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		GTE(string l, string r):BP(l,r){};
		GTE(string l, Cell *r):BP(l,r){};
		GTE(Cell *l, string r):BP(l,r){};
		GTE(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion :BP

#pragma region class LTE
class LTE : public BP {
	protected:
		virtual bool Compare(Cell *l, Cell *r);
	public:
		LTE(string l, string r):BP(l,r){};
		LTE(string l, Cell *r):BP(l,r){};
		LTE(Cell *l, string r):BP(l,r){};
		LTE(Cell *l, Cell *r):BP(l,r){};
};
#pragma endregion :BP

#pragma region class AND
class AND : public P {
		P *l, *r;
	public:
		AND(P *_l, P *_r) {l = _l; r = _r;}
		virtual bool Evaluate(void* Row, list<CD> *cds);
};
#pragma endregion :P

#pragma region class OR
class OR : public P {
		P *l, *r;
	public:
		OR(P *_l, P *_r)  {l = _l; r = _r;}
		virtual bool Evaluate(void* Row, list<CD> *cds);
};
#pragma endregion  :P

#pragma region class NOT
	class NOT : public P {
		P *p;
	public:
		NOT(P *_p)  {p = _p;}
		virtual bool Evaluate(void* Row, list<CD> *cds);
};
#pragma endregion :P

#pragma endregion

#pragma region Helper Functon Declarations
	Types RecoverType(string *name, void* Row, list<CD> *cds);
	Cell* RecoverCell(string *name, void* Row, list<CD> *cds);
	size_t GetTypeSize(Types t);
	size_t sizeOfCD(list<CD> Columns);
	vector<string> split(string value, char delimeter);
#pragma endregion Helper Functon Declarations

}

#endif




